<?php

/**
 * Holds abstract class Mvc_Controller_Base
 *
 * @author Mark
 *
 * @package Library
 * @subpackage Mvc
 */

/**
 * Mvc_Controller_Base
 *
 * @todo write comment
 *
 * @author Mark
 */
abstract class Mvc_Controller_Base {

	/**
	 * Arguments
	 * @var array $_argv
	 */
	protected $_argv = array();

	/**
	 * Context resource
	 * @var Mvc_Context_Controller $_context
	 */
	protected $_context;

	/**
	 * Layout resource
	 * @var Mvc_View $_layout
	 */
	protected $_layout;

	/**
	 * Response resource
	 * @var Mvc_Response $_response
	 */
	protected $_response;
	
	
	/**
	 * View type
	 * @var string $_view
	 */
	protected $_view = 'Smarty';
	
	
	/**
	 * Variables
	 * @var array $_var
	 */
	protected $_var = array();
	
	/**
	 * Template file
	 *
	 * @var string $_template
	 */
	protected $_template = '';
	
	/**
	 * Module name
	 *
	 * @var string $_module
	 */
	protected $_module;
	
	/**
	 * Controller name
	 *
	 * @var string $_controller
	 */
	protected $_controller;

	/**
	 * Action name
	 *
	 * @var string $_action
	 */
	protected $_action;

	/**
	 * Constructor
	 *
	 * @return void
	 */
	public function __construct() {
		$this->_response = new Mvc_Response();
		$this->_template = 'default';
	}

	/**
	 * Magic method interceptor, redirects to context
	 *
	 * @param string $name
	 * @param array $arguments
	 * @throws Exception
	 * @return mixed
	 */
	public function __call($name, array $arguments) {
		if(in_array($name, get_class_methods($this->_getContext()))) {
			return $this->_getContext()->$name($arguments);
		}
		throw new Exception('Call to undefined method ' . $name);
	}

	/**
	 * Returns layout variable
	 *
	 * @param string $key
	 * @return string
	 */
	public function get($key) {
		return $this->$key;
	}

	/**
	 * Returns argument
	 *
	 * @param string $key
	 * @return string
	 */
	public function getArgument($key) {
		if(!isset($this->_argv[$key])) {
			throw new Exception('Argument ' . $key . ' does not exist');
		}
		return $this->_argv[$key];
	}

	/**
	 * Returns response resource
	 *
	 * @return Mvc_Response
	 */
	public function getResponse() {
		return $this->_response;
	}
	
	/**
	 * Returns Database resource
	 *
	 * @return Database
	 */
	public function getDb() {
		return $this->_getContext()->getDb();
	}
	
	/**
	 * Returns Mvc_Request
	 *
	 * @return Mvc_Request
	 */
	public function getRequest() {
		return $this->_getContext()->getRequest();
	}

	/**
	 * Initializes page
	 *
	 * @return void
	 */
	abstract public function init();

	/**
	 * Renders layout
	 *
	 * @return Mvc_Controller_Base (fluent interface)
	 */
	public function render() {
		
		$view = 'Mvc_View_'.$this->_view;
		$view = new $view($this->_module,$this->_controller,$this->_action,$this->_template);
		$view->setVar($this->_var);
		
		$this->getResponse()->setBody($view->render());
		
		return $this;
	}

	/**
	 * Sets layout variable
	 *
	 * @param array|string $key
	 * @param mixed $value (optional)
	 * @return Mvc_Controller_Base
	 */
	public function set($key, $value = null) {
		if(is_array($key)) {
			$function = __FUNCTION__;
			foreach($key as $k => $v) {
				$this->$function($k, $v);
			}
		}
		else {
			$this->_var[$key] = $value;
		}
		return $this;
	}
	
	/**
	 * Sets content variable
	 *
	 * @param string $key
	 * @param mixed $value
	 * @return void
	 */
	public function __set($key, $value) {
		$this->set($key, $value);
	}
	
	/**
	 * Returns content variable
	 *
	 * @param string $key
	 * @return mixed
	 */
	public function __get($key) {
		return isset($this->_var[$key]) ? Util::quote($this->_var[$key]) : '';
	}
	
	/**
	 * Checks whether variable is set
	 *
	 * @param string $key
	 * @return boolean
	 */
	public function __isset($key) {
		return isset($this->_var[$key]);
	}
	
	/**
	 * Will clear all currently assigned vars
	 */
	public function unSetAll(){
		$this->_var = array();
	}

	/**
	 * Sets arguments
	 *
	 * @param array $argv
	 * @return Mvc_Controller_Base (fluent interface)
	 */
	public function setArguments(array $argv) {
		$this->_argv = $argv;
		return $this;
	}

	/**
	 * Sets context
	 *
	 * @param Mvc_Context_Controller $context
	 * @return Base (fluent interface)
	 */
	public function setContext(Mvc_Context_Controller $context) {
		$this->_context = $context;
		return $this;
	}

	/**
	 * Sets layout
	 *
	 * @param string $file
	 * @return Mvc_Controller_Base (fluent interface)
	 */
	public function setLayout($module,$controller,$action) {
//		if($this->_view && $this->_view != ""){
//			$view = 'Mvc_View_'.$this->_view;
//			$this->_layout = new $view();
//		}else{
//			$this->_layout = new Mvc_View();
//		}
		$this->_module = $module;
		$this->_controller = $controller;
		$this->_action = $action;
		$this->init();// initialize page
		return $this;
	}

	/**
	 * Links template to event
	 *
	 * @param string $event
	 * @param string $template
	 * @return Mvc_View
	 */
	public function setTemplate($event, $template) {
		return $this->_layout;
	}

	/**
	 * Returns context resource
	 *
	 * @return Mvc_Context_Controller
	 */
	protected function _getContext() {
		return $this->_context;
	}

	/**
	 * Returns layout resource
	 *
	 * @return Mvc_View
	 */
	protected function _getLayout() {
		return $this->_layout;
	}

}
